
import { _decorator, Component, Node, Mesh, utils, MeshRenderer } from 'cc';
import GameConfig from '../../Script/GameSpecial/GameConfig';
import yyComponent from '../../Script/Common/yyComponent';
const { ccclass, property } = _decorator;

const f3 = 0.3333;
const f6 = 0.6667;
const charUV = {
    0: [0, 0.25, 0, f3],
    1: [0.25, 0.5, 0, f3],
    2: [0.5, 0.75, 0, f3],
    3: [0.75, 1, 0, f3],

    4: [0, 0.25, f3, f6],
    5: [0.25, 0.5, f3, f6],
    6: [0.5, 0.75, f3, f6],
    7: [0.75, 1, f3, f6],

    8: [0, 0.25, f6, 1],
    9: [0.25, 0.5, f6, 1],
    x: [0.5, 0.75, f6, 1],
    d: [0.75, 1, f6, 1],
};


@ccclass('ScoreRoad')
export class ScoreRoad extends yyComponent {

    /**数字字体高度 */
    protected static fontHeight: number = 3;
    /**数字距行线底部距离 */
    protected static fontOffsetZ: number = 1;
    /**数字行高 */
    protected static fontLineHeight: number;
    //以下数值 *10，是为了避免小数精度导致字符错误
    /**倍数增加间隔 * 10 的值 */
    protected static scoreValueStep: number;
    /**倍数初始值 * 10 */
    protected static startScore: number = 10;
    /**倍数最大值 * 10 */
    protected static maxScore: number;
    protected static meshData;
    protected static _mesh: Mesh;
    protected static get mesh(): Mesh {
        if (!this._mesh) {
            this.createMesh();
        }
        return this._mesh;
    }
    protected static createMesh() {
        this.meshData = {
            positions: [],
            normals: [],
            indices: [],
            uvs: [],
        };
        this.fontLineHeight = GameConfig.GameRule.scoreRoadStepLen;
        this.scoreValueStep = GameConfig.GameRule.scoreRoadStep * 10;
        this.maxScore = GameConfig.GameRule.scoreRoadMax * 10;
        let r = GameConfig.GameRule.roadHalfWidth - 0.1;
        let w = this.fontHeight * 114 / 150;
        let radian = w * 3.3333 / r;
        // let radianScope = GameConfig.GameRule.roadMaxRadian;
        let radianScope = radian;
        let startRadian = Math.PI * 0.5 - radianScope * 0.5;
        let endRadian = Math.PI * 0.5 + radianScope * 0.5;
        this.addFloatMesh(startRadian, startRadian + radianScope * 0.3);
        this.addCharDot(startRadian + radianScope * 0.25, startRadian + radianScope * 0.45);
        this.addIntMesh(startRadian + radianScope * 0.4, startRadian + radianScope * 0.7);
        this.addCharX(startRadian + radianScope * 0.7, endRadian);
        this.addLineMesh(startRadian - 3 / r, endRadian + 3 / r);

        this._mesh = new Mesh();
        this._mesh = utils.createMesh(this.meshData);
    }
    /**
     * 小数点部分的网格
     * @param startRadian 起始弧度
     * @param endRadian 终点弧度
     */
    protected static addFloatMesh(startRadian: number, endRadian: number) {
        let vertOffset = this.meshData.positions.length / 3;
        let r = GameConfig.GameRule.roadHalfWidth - 0.1;//半径
        let radianCount = 6;
        let stepRadian = (endRadian - startRadian) / (radianCount - 1);
        let inPI = 0.25 / (endRadian - startRadian);
        for (let i = 0; i <= radianCount; ++i) {
            let radian = startRadian + i * stepRadian;
            let s1 = Math.sin(radian);
            let c1 = Math.cos(radian);
            let x = r * c1;
            let y = -r * s1;
            let offsetUVX = i * stepRadian * inPI;
            let v = 0;
            let z = -this.fontOffsetZ;
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                //坐标
                this.meshData.positions.push(x, y, z, x, y, z - this.fontHeight);
                z -= this.fontLineHeight;
                //uv
                let uv = charUV[v];
                this.meshData.uvs.push(uv[1] - offsetUVX, uv[3], uv[1] - offsetUVX, uv[2]);

                v += this.scoreValueStep;
                if (v >= 10) {
                    v -= 10;
                }
            }
        }
        //三角面
        let index = vertOffset;
        let zCount = Math.floor((this.maxScore - this.startScore) / this.scoreValueStep) * 2 + 2;
        for (let i = 0; i < radianCount - 1; ++i) {
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                this.meshData.indices.push(index, index + 1, index + zCount, index + 1, index + 1 + zCount, index + zCount);
                index += 2;
            }
        }
    }
    protected static addIntMesh(startRadian: number, endRadian: number) {
        let vertOffset = this.meshData.positions.length / 3;
        let r = GameConfig.GameRule.roadHalfWidth - 0.1;//半径
        let radianCount = 6;
        let stepRadian = (endRadian - startRadian) / (radianCount - 1);
        let inPI = 0.25 / (endRadian - startRadian);
        for (let i = 0; i <= radianCount; ++i) {
            let radian = startRadian + i * stepRadian;
            let s1 = Math.sin(radian);
            let c1 = Math.cos(radian);
            let x = r * c1;
            let y = -r * s1;
            let offsetUVX = i * stepRadian * inPI;
            let z = -this.fontOffsetZ;
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                //坐标
                this.meshData.positions.push(x, y, z, x, y, z - this.fontHeight);
                z -= this.fontLineHeight;
                //uv
                let iv = Math.floor(score * 0.1);
                let uv = charUV[iv];
                this.meshData.uvs.push(uv[1] - offsetUVX, uv[3], uv[1] - offsetUVX, uv[2]);
            }
        }
        //三角面
        let index = vertOffset;
        let zCount = Math.floor((this.maxScore - this.startScore) / this.scoreValueStep) * 2 + 2;
        for (let i = 0; i < radianCount - 1; ++i) {
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                this.meshData.indices.push(index, index + 1, index + zCount, index + 1, index + 1 + zCount, index + zCount);
                index += 2;
            }
        }
    }
    protected static addCharDot(startRadian: number, endRadian: number) {
        let vertOffset = this.meshData.positions.length / 3;
        let r = GameConfig.GameRule.roadHalfWidth - 0.1;//半径
        let radianCount = 2;
        let stepRadian = (endRadian - startRadian) / (radianCount - 1);
        let inPI = 0.25 / (endRadian - startRadian);
        let uv = charUV.d;
        for (let i = 0; i <= radianCount; ++i) {
            let radian = startRadian + i * stepRadian;
            let s1 = Math.sin(radian);
            let c1 = Math.cos(radian);
            let x = r * c1;
            let y = -r * s1;
            let offsetUVX = i * stepRadian * inPI;
            let z = -this.fontOffsetZ;
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                //坐标
                this.meshData.positions.push(x, y, z, x, y, z - this.fontHeight);
                z -= this.fontLineHeight;
                //uv
                this.meshData.uvs.push(uv[1] - offsetUVX, uv[3], uv[1] - offsetUVX, uv[2]);
            }
        }
        //三角面
        let index = vertOffset;
        let zCount = Math.floor((this.maxScore - this.startScore) / this.scoreValueStep) * 2 + 2;
        for (let i = 0; i < radianCount - 1; ++i) {
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                this.meshData.indices.push(index, index + 1, index + zCount, index + 1, index + 1 + zCount, index + zCount);
                index += 2;
            }
        }
    }
    protected static addCharX(startRadian: number, endRadian: number) {
        let vertOffset = this.meshData.positions.length / 3;
        let r = GameConfig.GameRule.roadHalfWidth - 0.1;//半径
        let radianCount = 6;
        let stepRadian = (endRadian - startRadian) / (radianCount - 1);
        let inPI = 0.25 / (endRadian - startRadian);
        let uv = charUV.x;
        for (let i = 0; i <= radianCount; ++i) {
            let radian = startRadian + i * stepRadian;
            let s1 = Math.sin(radian);
            let c1 = Math.cos(radian);
            let x = r * c1;
            let y = -r * s1;
            let offsetUVX = i * stepRadian * inPI;
            let z = -this.fontOffsetZ;
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                //坐标
                this.meshData.positions.push(x, y, z, x, y, z - this.fontHeight);
                z -= this.fontLineHeight;
                //uv
                this.meshData.uvs.push(uv[1] - offsetUVX, uv[3], uv[1] - offsetUVX, uv[2]);
            }
        }
        //三角面
        let index = vertOffset;
        let zCount = Math.floor((this.maxScore - this.startScore) / this.scoreValueStep) * 2 + 2;
        for (let i = 0; i < radianCount - 1; ++i) {
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                this.meshData.indices.push(index, index + 1, index + zCount, index + 1, index + 1 + zCount, index + zCount);
                index += 2;
            }
        }
    }
    //分割线
    protected static addLineMesh(startRadian: number, endRadian: number) {
        let vertOffset = this.meshData.positions.length / 3;
        let r = GameConfig.GameRule.roadHalfWidth - 0.1;//半径
        let radianCount = 26;
        let stepRadian = (endRadian - startRadian) / (radianCount - 1);
        let uvx = 0.375;
        let uvy = 0.25;
        let lineHeight = 0.1;
        for (let i = 0; i <= radianCount; ++i) {
            let radian = startRadian + i * stepRadian;
            let s1 = Math.sin(radian);
            let c1 = Math.cos(radian);
            let x = r * c1;
            let y = -r * s1;
            let z = lineHeight * 0.5;
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                //坐标
                this.meshData.positions.push(x, y, z, x, y, z - lineHeight);
                z -= this.fontLineHeight;
                //uv
                this.meshData.uvs.push(uvx, uvy, uvx, uvy);
            }
        }
        //三角面
        let index = vertOffset;
        let zCount = Math.floor((this.maxScore - this.startScore) / this.scoreValueStep) * 2 + 2;
        let c = 0;
        for (let i = 0; i < radianCount - 1; ++i) {
            index = vertOffset + zCount * i;
            for (let score = this.startScore; score <= this.maxScore; score += this.scoreValueStep) {
                this.meshData.indices.push(index, index + 1, index + zCount, index + 1, index + 1 + zCount, index + zCount);
                index += 2;
            }
            // if (i % 4 == 0) {
            //     i += 2;
            // }
            c++;
            if (c % 2 == 0) {
                c = 0;
                i += 1;
            }
            // if (i % 2 == 0) {
            //     i += 1;
            // }
        }
    }

    protected initSub() {
        this.initMesh();
    }

    @property(MeshRenderer)
    protected meshRender: MeshRenderer = null;
    protected initMesh() {
        this.meshRender.mesh = ScoreRoad.mesh;
    }
}
